# Copyright (c) 2018 Presto Labs Pte. Ltd.
# Author: xguo

import time
import json
import warnings

try:
  import bitmex
except ImportError as e:
  pass

import coin.exchange.base.kr_rest.native_public_client_base as npubcb
from coin.exchange.base.kr_rest.rest_client_base import RestUpdate


class BitmexNativePublicClient(npubcb.NativePublicClientBase):
  def __init__(self, timeout=5, test=False):
    url = "https://www.bitmex.com/api/v1"
    npubcb.NativePublicClientBase.__init__(self, url=url, timeout=timeout)
    with warnings.catch_warnings():
      warnings.simplefilter("ignore")
      self._client = bitmex.bitmex(test=test)
    self._valid_kline_period = ['1m', '5m', '1h', '1d']

  def check_kline_period(self, kline_period):
    assert kline_period in self._valid_kline_period, \
        'Invalid kline period!'

  def _get_as_json(self, endpoint, method, **kwargs):
    req_timestamp = time.time()
    with warnings.catch_warnings():
      warnings.simplefilter("ignore")
      fut = getattr(getattr(self._client, endpoint), method)(**kwargs)
    json_msg, response = fut.result(timeout=self.timeout)
    if response.status_code == 200:
      res_timestamp = time.time()
      return RestUpdate(req_timestamp, res_timestamp, json_msg)
    else:
      res_timestamp = time.time()
      return RestUpdate(req_timestamp, res_timestamp, None, status=response.status_code)

  def get_instrument_active(self):
    endpoint = 'Instrument'
    method = 'Instrument_getActive'
    return self._get_as_json(endpoint, method)

  def get_instrument_open(self, symbol=None):
    if symbol is not None:
      assert isinstance(symbol, str), 'symbol must be of string type or None.'
    endpoint = 'Instrument'
    method = 'Instrument_get'
    query_filter = '{"state": "Open"}'
    params = {
        "filter": query_filter,
        "count": 300,
    }
    if symbol:
      params['symbol'] = symbol
    update = self._get_as_json(endpoint, method, **params)
    assert isinstance(update.msg, list)
    return update

  def get_orderbook_l2(self, symbol, depth=25):
    endpoint = 'OrderBook'
    method = 'OrderBook_getL2'
    update = self._get_as_json(endpoint, method, symbol=symbol, depth=depth)
    return update

  def get_quote(self, symbol):
    endpoint = 'Quote'
    method = 'Quote_get'
    return self._get_as_json(endpoint, method, symbol=symbol, reverse=True, count=1)

  def query_trade(self, symbol):
    endpoint = 'Trade'
    method = 'Trade_get'
    params = {
        'symbol': symbol,
    }
    return self._query(endpoint, method, params)

  def query_trade_bucketed(self, symbol, kline_period, start_time, end_time):
    self.check_kline_period(kline_period)
    endpoint = 'Trade'
    method = 'Trade_getBucketed'
    params = {
        'symbol': symbol,
        'binSize': kline_period,
        'startTime': start_time,
        'endTime': end_time,
        'partial': True,
        'reverse': True,
    }
    return self._get_as_json(endpoint, method, **params)

  def queryAll(self):
    pass


if __name__ == "__main__":
  client = BitmexNativePublicClient()
  update = client.get_instrument_active()
  print(json.dumps(update.msg, indent=2, default=str))

  update = client.get_instrument_open()
  print(json.dumps(update.msg, indent=2, default=str))

  update = client.query_trade_bucketed('XBTUSD', '1d', 50)
  print(json.dumps(update.msg, indent=2, default=str))
